%%%-------------------------------------------------------------------
%%% @author wukai
%%% @copyright (C) 2017, <COMPANY>
%%% @doc
%%%
%%% @end
%%% Created : 20. 十二月 2017 17:46
%%%-------------------------------------------------------------------
-module(dispatch_server).
-author("wukai").
-behaviour(gen_server).
-define(SUBSCRIBE_TABLE, subscriber).

-record(subscriber, {
  client,%%客户端id
  filter,%%主题过滤器
  reg,%%替换为正则表达式
  pid,
  qos%%消息质量
}).


%% API
-export([start_link/0]).
-export([send_dispatch/1]).
-export([send_or_save/3]).

-export([init/1,
  handle_call/3,
  handle_cast/2,
  handle_info/2,
  terminate/2,
  code_change/3]).

-define(SERVER, ?MODULE).
-record(state, {msg_count = 0}).

start_link() ->
  gen_server:start_link({local, ?SERVER}, ?MODULE, [], []).
init([]) ->
  {ok, #state{}}.
handle_call(_Request, _From, State) ->
  {reply, ok, State}.

%%发布消息
handle_cast({dispatch, M}, State) ->
  C = State#state.msg_count + 1,
  dispatch(M),
  {noreply, State#state{msg_count = C}};
handle_cast(_Request, State) ->
  {noreply, State}.

handle_info(_Info, State) ->
  {noreply, State}.
terminate(_Reason, _State) ->
  ok.
code_change(_OldVsn, State, _Extra) ->
  {ok, State}.

dispatch(M) ->
  List = ets:lookup(?SUBSCRIBE_TABLE, publish_frame:topic(M)),
  lists:foreach(fun(E) ->
    send_or_save(E#subscriber.client,
      publish_frame:wrap_dispatch(M, E#subscriber.qos), E#subscriber.pid) end, List).

send_or_save(Client, Msg, Pid) ->
  Qos = publish_frame:qos(Msg),
  case is_process_alive(Pid) of
    false when Qos > 0 -> cache_server:send_save(Client,[Msg]);
    true -> mqtt_process:send_msg(Pid, Msg);
    _ -> ok
  end.

send_dispatch(M) -> gen_server:cast(?MODULE, {dispatch, M}).